

#include "Acceptor.hpp"
#include "EventLoop.hpp"
#include "Channel.hpp"
#include "InetAddress.hpp"
#include "Logger.hpp"
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>

namespace zephyr {

static int createNonBlocking() {
    int sockfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP);
    if (sockfd < 0) {
        LOG_FATAL("%s:%s:%d listen socket create err: %s\n", __FILE__, __FUNCTION__, __LINE__, strerror(errno));
    }
    return sockfd;
}

Acceptor::Acceptor(EventLoop *loop, const InetAddress &listenaddr, bool reuseport)
    : m_loop(loop)
    , m_acceptSocket(createNonBlocking())
    , m_acceptChannel(loop, m_acceptSocket.fd())
    , m_listening(false) {
    
    m_acceptSocket.setReuseAddr(true);
    m_acceptSocket.setReusePort(true);
    m_acceptSocket.bindAddress(listenaddr);
    
    // 设置接受连接回调
    // std::bind绑定后的可调用对象可以接受任意数量的额外参数，多余的参数会被自动忽略。
    // handRead 没有参数，而setReadCallback的回调有参数，在调用回调是会忽略传入的参数
    m_acceptChannel.setReadCallback(std::bind(&Acceptor::handleRead, this));
    
}

Acceptor::~Acceptor() {
    m_acceptChannel.disableAll();
    m_acceptChannel.remove();
}

void Acceptor::listen() {
    m_listening = true;
    m_acceptSocket.listen();
    // 注册到poller中
    m_acceptChannel.enableReading();
}

void Acceptor::handleRead() {
    InetAddress peeraddr;
    int connfd = m_acceptSocket.accept(&peeraddr);
    if (connfd >= 0) {
        if(m_newconnectioncb) {
            m_newconnectioncb(connfd, peeraddr);
        } else {
            close(connfd);
        }
    } else {
        LOG_ERROR("%s:%s:%d accept err: %s\n", __FILE__, __FUNCTION__, __LINE__, strerror(errno));
        if (errno == EMFILE) {
            LOG_ERROR("%s:%s:%d sockfd reached limit.\n", __FILE__, __FUNCTION__, __LINE__);
        }
    }
}

}
